package com.ygp.dtp.core.refresh.abstracts;

import com.ygp.dtp.common.config.properties.DtpProperties;
import com.ygp.dtp.common.constant.DynamicTpConstant;
import com.ygp.dtp.common.enums.ConfigFileTypeEnum;
import com.ygp.dtp.common.event.RefreshEvent;
import com.ygp.dtp.common.holder.ApplicationContextHolder;
import com.ygp.dtp.core.DynamicThreadPoolRegistry;
import com.ygp.dtp.core.handler.ConfigHandler;
import com.ygp.dtp.core.refresh.Refresher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * @description: 重新刷新配置内容抽象类
 * @motto: 代码源于生活，高于生活艺术
 * @author: zhouhengzhe
 * @date: 2022/8/9 17:27
 * @since 1.0
 **/
@Slf4j
public abstract class AbstractRefresher implements Refresher {

    @Resource
    private DtpProperties dtpProperties;

    /**
     * 重新刷新配置内容
     *
     * @param content  刷新内容
     * @param fileType 文件类型
     */
    @Override
    public void refresh(String content, ConfigFileTypeEnum fileType) {

        /**
         * 内容，文件类型不为空
         */
        if (Objects.nonNull(content) || Objects.nonNull(fileType)) {
            ConfigHandler instance = ConfigHandler.getInstance();
            try {
                Map<Object, Object> parse = instance.parse(content, fileType);
                doRefresh(parse);
            } catch (IOException e) {
                log.error("动态数据源解析内容失败, 内容为: {}, 文件类型为: {}", content, fileType, e);
            }
        }

    }

    /**
     * 准备刷新，可以看一下这篇文章：https://article.itxueyuan.com/kyW327
     * 主要是对MapConfigurationPropertySource的一些介绍与使用
     *
     * @param properties
     */
    private void doRefresh(Map<Object, Object> properties) {
        // 自定义ConfigurationProperty源信息
        MapConfigurationPropertySource configurationPropertySource = new MapConfigurationPropertySource(properties);
        //创建Binder绑定类
        Binder binder = new Binder(configurationPropertySource);
        DtpProperties bindDtpProperties = binder.bind(DynamicTpConstant.MAIN_PROPERTIES_PREFIX, Bindable.ofInstance(this.dtpProperties)).get();
        DynamicThreadPoolRegistry.refresh(bindDtpProperties);
        publishEvent();
    }

    /**
     * 发布监听事件 具体消费者，请看 DtpWebRefreshListener
     */
    private void publishEvent() {
        ApplicationContextHolder.getInstance().publishEvent(new RefreshEvent(this, dtpProperties));
    }
}
